﻿//Copyright (C) <2013>  <jonathan cleeve norton> All Rights Reserved 
//Contact jon.norton@fin-plus.co.uk website <http://www.fin-plus.co.uk/>
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Windows.Threading;
using FinPlusInterfaces;

namespace FinPlusBaseCore
{
    public sealed class DPods : ObservableCollection<IDPod>, IDPods
    {
        public event PropertyChangedEventHandler PodChanged, ColumnChanged;
        public override event NotifyCollectionChangedEventHandler CollectionChanged;

        private ConcurrentDictionary<string, IDPod> index = new ConcurrentDictionary<string, IDPod>();

        public DPods() { }

        public DPods(IPods pods)
        {
            foreach (var pod in pods.Values)
                Add(new DPod(pod));
        }

        //public
        public new void Add(IDPod dPod)
        {
            this.CheckReentrancy();
            base.Add(dPod);
            object id = null;
            if (dPod.TryGetObject(PodField.Id.ToString(), out id))
                index[id.ToString()] = dPod;

            dPod.PropertyChanged += NotifyPodChanged;
            dPod.PropertyColumn += NotifyColumnChanged;
        }

        public bool Remove(string id)
        {
            if (index.ContainsKey(id))
            {
                IDPod dPod = null;
                this.CheckReentrancy();
                base.Remove(index[id]);
                index.TryRemove(id.ToString(), out dPod);
                return true;
            }
            return false;
        }

        public new void Clear()
        {
            base.Clear();
            index.Clear();
        }

        public void Replace(IPods pods)
        {
            Clear();
            foreach (var pod in pods.Values)
                Add(new DPod(pod));
        }

        public bool TryGet(string id, out IDPod value)
        {
            return index.TryGetValue(id, out value);
        }

        public IPods ToPods()
        {
            var pods = new Pods();
            foreach (var dPod in this)
                pods.Add(dPod.ToPod());

            return pods;
        }

        //private
        protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs a)
        { 
            using (BlockReentrancy())
            {
                var collectionChanged = this.CollectionChanged;
                if (collectionChanged == null) 
                    return;
                foreach (NotifyCollectionChangedEventHandler handler in collectionChanged.GetInvocationList())
                {
                    var dispObj = (DispatcherObject)handler.Target;
                    if (dispObj != null)
                    {
                        var disp = dispObj.Dispatcher;
                        if (disp != null && !disp.CheckAccess())
                        {
                            disp.BeginInvoke((Action)(() => handler.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))), DispatcherPriority.DataBind);
                            continue;
                        }
                    }
                    handler.Invoke(this, a);
                }
            }
        }

        private void NotifyPodChanged(object s, PropertyChangedEventArgs a)
        {
            if (PodChanged != null)
                PodChanged.Invoke(s, a);
        }

        private void NotifyColumnChanged(object s, PropertyChangedEventArgs a)
        {
            if (ColumnChanged != null)
                ColumnChanged.Invoke(s, a);
        }
    }
}
